package com.yfqy.app.modules.order.builder;

import com.yfqy.app.configure.Idgenerator.SnowflakeIdGenerator;
import com.yfqy.app.modules.order.dto.OrderAmountDTO;
import com.yfqy.app.modules.order.dto.OrderItemDTO;
import com.yfqy.app.modules.order.dto.OrderItemRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.List;

@Component
public class OrderItemBuilder {

    private static final int CALC_SCALE = 10; // 中间计算精度
    private static final int RESULT_SCALE = 2; // 结果精度

    @Autowired
    private SnowflakeIdGenerator idGenerator;

    public List<OrderItemDTO> buildItems(List<OrderItemRequest> itemRequests,
                                         Long promotionId,
                                         OrderAmountDTO orderAmount,
                                         Long orderId) {
        List<OrderItemDTO> items = new ArrayList<>();

        // 计算所有商品总金额
        BigDecimal itemsTotalAmount = orderAmount.getTotalAmount();

        // 初始化分摊累计值
        BigDecimal allocatedDiscounts = BigDecimal.ZERO;
        BigDecimal allocatedPoints = BigDecimal.ZERO;

        for (int i = 0; i < itemRequests.size(); i++) {
            OrderItemRequest request = itemRequests.get(i);
            OrderItemDTO item = buildBaseItem(request, orderId, promotionId);

            // 计算当前商品金额
            BigDecimal itemAmount = item.getTotalPrice();

            // 分摊优惠金额
            if (orderAmount.getDiscountAmount().compareTo(BigDecimal.ZERO) == 0) {
                item.setDiscountPrice(BigDecimal.ZERO);
            } else if (i == itemRequests.size() - 1) {
                // 最后一项使用差额补齐
                BigDecimal discount = orderAmount.getDiscountAmount().subtract(allocatedDiscounts)
                        .setScale(RESULT_SCALE, RoundingMode.HALF_UP);
                item.setDiscountPrice(discount);
            } else {
                // 按比例分摊
                BigDecimal ratio = itemAmount.divide(itemsTotalAmount, CALC_SCALE, RoundingMode.HALF_UP);
                BigDecimal discount = orderAmount.getDiscountAmount().multiply(ratio)
                        .setScale(RESULT_SCALE, RoundingMode.HALF_UP);
                item.setDiscountPrice(discount);
                allocatedDiscounts = allocatedDiscounts.add(discount);
            }

            // 分摊积分金额
            if (orderAmount.getPointAmount().compareTo(BigDecimal.ZERO) == 0) {
                item.setPointPrice(BigDecimal.ZERO);
            } else if (i == itemRequests.size() - 1) {
                // 最后一项使用差额补齐
                BigDecimal points = orderAmount.getPointAmount().subtract(allocatedPoints)
                        .setScale(RESULT_SCALE, RoundingMode.HALF_UP);
                item.setPointPrice(points);
            } else {
                // 按比例分摊
                BigDecimal ratio = itemAmount.divide(itemsTotalAmount, CALC_SCALE, RoundingMode.HALF_UP);
                BigDecimal points = orderAmount.getPointAmount().multiply(ratio)
                        .setScale(RESULT_SCALE, RoundingMode.HALF_UP);
                item.setPointPrice(points);
                allocatedPoints = allocatedPoints.add(points);
            }

            // 计算实际支付单价
            calculateActualPrice(item);

            items.add(item);
        }

        return items;
    }

    private OrderItemDTO buildBaseItem(OrderItemRequest request, Long orderId, Long promotionId) {
        OrderItemDTO item = new OrderItemDTO();
        item.setId(idGenerator.nextId());
        item.setOrderId(orderId);
        item.setSpuId(request.getSpuId());
        item.setSkuId(request.getSkuId());
        item.setSpuName(request.getSpuName());
        item.setSkuSpecs(request.getSkuSpecs());
        item.setSkuImage(request.getSkuImage());
        item.setSkuNumber(request.getQuantity());
        item.setUnitPrice(request.getUnitPrice());
        item.setTotalPrice(calculateItemAmount(request));
        item.setPromotionId(promotionId);
        item.setPromotionProductId(request.getPromotionProductId());
        return item;
    }

    private BigDecimal calculateItemAmount(OrderItemRequest request) {
        return request.getUnitPrice().multiply(BigDecimal.valueOf(request.getQuantity()))
                .setScale(RESULT_SCALE, RoundingMode.HALF_UP);
    }

    private void calculateActualPrice(OrderItemDTO item) {
        BigDecimal totalDiscount = item.getDiscountPrice().add(item.getPointPrice());
        BigDecimal actualTotalPrice = item.getTotalPrice().subtract(totalDiscount);
        item.setActualPrice(actualTotalPrice);

    }
}